using System;
using FwkLight.Domain.Fetching;
using NHibernate;
using NHibernate.Criterion;

namespace FwkLight.Domain
{
  public abstract class FullSpecification<T> : IFullSpecification<T>
  {
    protected FullSpecification()
    {
      IEntityAliasParser entityAliasParser = new EntityAliasParser();
      RootAlias = entityAliasParser.ParseAliasFor(typeof (T), null);
    }

    public FullSpecification<T> WithRootAlias(string alias)
    {
      RootAlias = alias;
      return this;
    }

    protected string RootAlias { get; set; }

    public abstract bool IsSatisfiedBy(T entity);

    public abstract DetachedCriteria EnsureThatWillBeSatisfiedBy(DetachedCriteria criteria);

    public abstract ICriteria EnsureThatWillBeSatisfiedBy(ICriteria criteria);
  }

	public abstract class FullSpecification<T, Param1> : IFullSpecification<T, Param1>
	{
		protected FullSpecification()
		{
			IEntityAliasParser entityAliasParser = new EntityAliasParser();
			RootAlias = entityAliasParser.ParseAliasFor(typeof(T), null);
		}

		public FullSpecification<T, Param1> WithRootAlias(string alias)
		{
			RootAlias = alias;
			return this;
		}

		protected string RootAlias { get; set; }

		public abstract bool IsSatisfiedBy(T entity, Param1 param1);

		public abstract DetachedCriteria EnsureThatWillBeSatisfiedBy(DetachedCriteria criteria, Param1 param1);

		public abstract ICriteria EnsureThatWillBeSatisfiedBy(ICriteria criteria, Param1 param1);
	}

  public abstract class FullSpecification<T, Param1, Param2> : IFullSpecification<T, Param1, Param2>
  {
    protected FullSpecification()
    {
      IEntityAliasParser entityAliasParser = new EntityAliasParser();
      RootAlias = entityAliasParser.ParseAliasFor(typeof(T), null);
    }

    public FullSpecification<T, Param1, Param2> WithRootAlias(string alias)
    {
      RootAlias = alias;
      return this;
    }

    protected string RootAlias { get; set; }

    public abstract bool IsSatisfiedBy(T entity, Param1 param1, Param2 param2);

    public abstract DetachedCriteria EnsureThatWillBeSatisfiedBy(DetachedCriteria criteria, Param1 param1, Param2 param2);

    public abstract ICriteria EnsureThatWillBeSatisfiedBy(ICriteria criteria, Param1 param1, Param2 param2);
  }

  public abstract class FullSpecification<T, Param1, Param2, Param3> : IFullSpecification<T, Param1, Param2, Param3>
  {
    protected FullSpecification()
    {
      IEntityAliasParser entityAliasParser = new EntityAliasParser();
      RootAlias = entityAliasParser.ParseAliasFor(typeof(T), null);
    }

    public FullSpecification<T, Param1, Param2, Param3> WithRootAlias(string alias)
    {
      RootAlias = alias;
      return this;
    }

    protected string RootAlias { get; set; }

    public abstract bool IsSatisfiedBy(T entity, Param1 param1, Param2 param2, Param3 param3);

    public abstract DetachedCriteria EnsureThatWillBeSatisfiedBy(DetachedCriteria criteria, Param1 param1, Param2 param2, Param3 param3);

    public abstract ICriteria EnsureThatWillBeSatisfiedBy(ICriteria criteria, Param1 param1, Param2 param2, Param3 param3);
  }

  public abstract class FullSpecification<T, Param1, Param2, Param3, Param4> : IFullSpecification<T, Param1, Param2, Param3, Param4>
  {
    protected FullSpecification()
    {
      IEntityAliasParser entityAliasParser = new EntityAliasParser();
      RootAlias = entityAliasParser.ParseAliasFor(typeof(T), null);
    }

    public FullSpecification<T, Param1, Param2, Param3, Param4> WithRootAlias(string alias)
    {
      RootAlias = alias;
      return this;
    }

    protected string RootAlias { get; set; }

    public abstract bool IsSatisfiedBy(T entity, Param1 param1, Param2 param2, Param3 param3, Param4 param4);

    public abstract DetachedCriteria EnsureThatWillBeSatisfiedBy(DetachedCriteria criteria, Param1 param1, Param2 param2, Param3 param3, Param4 param4);

    public abstract ICriteria EnsureThatWillBeSatisfiedBy(ICriteria criteria, Param1 param1, Param2 param2, Param3 param3, Param4 param4);
  }
}